/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2020. All rights reserved.
 * Description: header file of the external interfaces compatible with SDP V1

 * Create: 2014-06-16

 */

#ifndef KMC_SRC_SDP_SDPV1_ITF_H
#define KMC_SRC_SDP_SDPV1_ITF_H

#include "wsecv2_type.h"
#include "sdpv3_type.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

/* Contains the length of reserved bytes, which cannot be changed. */
#define SDP_CIPHER_HEAD_LEN     68  // SDP_CIPHER_HEAD_LEN is sizeof(SdpCipherHeader) + 8 bytes(reserve)
#define SDP_HMAC_HEAD_LEN       44  // SDP_HMAC_HEAD_LEN is sizeof(SdpHmacHeader) + 8 bytes(reserve)
#define SDP_PWD_HEAD_LEN        40  // SDP_PWD_HEAD_LEN is sizeof(SdpPwdHeader) + 8 bytes(reserve)
#define SDP_CIPHER_FILE_FLAG    32

typedef enum {
    SDP_CFT_FILE_HDR = 1, /* Ciphertext file header */
    SDP_CFT_CIPHER_HDR,   /* Ciphertext header */
    SDP_CFT_CIPHER_BODY,  /* Ciphertext body */
    SDP_CFT_HMAC_VAL      /* HMAC value */
} SdpCipherFileTlv;

/* Symmetrically encrypted data header */
#pragma pack(1)
typedef struct TagSdpCipherHeader {
    WsecUint32    version;            /* Data protection module version */
    /*
     * Indicates whether the plaintext HMAC is included.
     * If the HMAC is included, the plaintext HMAC is placed after the ciphertext.
     */
    WsecUint32    hmacFlag;
    WsecUint32    domain;             /* Field corresponding to the key ID */
    WsecUint32    algId;              /* Algorithm ID */
    WsecUint32    keyId;              /* Key ID used to calculate the HMAC */
    /* Iteration round, which is configured by the application for the key management module to derive working keys. */
    WsecUint32    iter;
    unsigned char salt[SDP_SALT_LEN]; /* Salt generated by the data protection module. */
    unsigned char iv[SDP_IV_MAX_LEN]; /* Salt generated by the data protection module. */
    WsecUint32    cipherLen;          /* Length of the encrypted ciphertext data */
} SdpCipherHeader;
#pragma pack()

/* HMAC Header Definition */
#pragma pack(1)
typedef struct TagSdpHmacHeader {
    WsecUint32    version;            /* Data protection module version */
    WsecUint32    domain;             /* Field corresponding to the key ID */
    WsecUint32    algId;              /* Algorithm ID */
    WsecUint32    keyId;              /* Key ID used to calculate the HMAC */
    /* Iteration round, which is configured by the application for the key management module to derive working keys. */
    WsecUint32    iter;
    unsigned char salt[SDP_SALT_LEN]; /* Salt generated by the data protection module. */
} SdpHmacHeader;
#pragma pack()

#pragma pack(1)
typedef struct TagSdpCipherHeaderBuff {
    union {
        unsigned char   buff[SDP_CIPHER_HEAD_LEN];
        SdpCipherHeader cipherHeader;
    };
} SdpCipherHeaderBuff;
#pragma pack()

#pragma pack(1)
typedef struct TagSdpHmacAlgAttributes {
    union {
        unsigned char buff[SDP_HMAC_HEAD_LEN];
        SdpHmacHeader hmacHeader;
    };
} SdpHmacAlgAttributes;
#pragma pack()

#pragma pack(1)
typedef struct TagSdpBodCipherHeader {
    SdpCipherHeaderBuff  cipherBuff;
    SdpHmacAlgAttributes hmacBuff;
} SdpBodCipherHeader;
#pragma pack()

#pragma pack(1)
typedef struct TagSdpCipherFileHeader {
    unsigned char flag[SDP_CIPHER_FILE_FLAG]; /* Format identifier length: 32 */
    WsecUint32    version;                    /* Ciphertext file version */
    WsecUint32    plainBlockLenMax;           /* Maximum length of a plaintext segment */
    WsecUint32    cipherBlockLenMax;          /* Maximum length of a ciphertext segment */
    WsecSysTime   createUtc;                  /* Ciphertext file generation time (UTC) */
    WsecSysTime   srcCreateTime;              /* Time when a source file is created. */
    WsecSysTime   srcEditTime;                /* Latest modification time of the source file. */
    unsigned char reserve[16];                /* 16 bytes are reserved. */
} SdpCipherFileHeader;
#pragma pack()

/* PWD header */
#pragma pack(1)
typedef struct TagSdpPwdHeader {
    WsecUint32    version;            /* Data protection module version */
    WsecUint32    algId;              /* Algorithm ID */
    /* Iteration round, which is configured by the application for the key management module to derive working keys. */
    WsecUint32    iter;
    unsigned char salt[SDP_SALT_LEN]; /* Salt generated by the data protection module. */
    WsecUint32    cipherLen;          /* Length of the encrypted password */
} SdpPwdHeader;
#pragma pack()

/* 1. Encryption and decryption */
/* Calculating the Ciphertext Length Based on the Plaintext Length */
/**
* @brief      Calculating the Ciphertext Length Based on the Plaintext Length.
* @param[in]  plainLen Plaintext Length.
* @param[out] cipherLen Ciphertext Length.
* @return     WSEC_SUCCESS on success, other error code on failure.
* @note
*  - Memory operation: no allocate memory.
*  - Thread safe:      Non-Thread-safe function, cannot be invoked concurrently with the WsecInitializeKmc,
*                      WsecInitializeEx, WsecInitializeKmcm, WsecResetEx, WsecResetHw, WsecFinalizeEx.
*  - OS difference:    no OS difference.
*  - Time consuming:   no consuming operation.
*/
unsigned long SdpGetCipherDataLen(WsecUint32 plainLen, WsecUint32 *cipherLen);

/* Small-size data encryption */
unsigned long SdpEncrypt(WsecUint32 domain,
    WsecUint32 cipherAlgId,
    WsecUint32 hmacAlgId,
    const unsigned char *plainText,
    WsecUint32 plainLen,
    unsigned char *cipherText,
    WsecUint32 *cipherLen);

/* Small data decryption */
unsigned long SdpDecrypt(WsecUint32 domain,
    const unsigned char *cipherText,
    WsecUint32 cipherLen,
    unsigned char *plainText,
    WsecUint32 *plainLen);

/* Stream Data Encryption - Start */
/**
* @brief      Stream Data Encryption - Start.
* @param[in]  domain Domain ID.
* @param[in]  cipherAlgId Encryption algorithm.
* @param[in]  hmacAlgId HMAC algorithm.
* @param[out] ctx Data protection context established during the current round of data encryption.
* @param[out] bodCipherHeader Ciphertext header.
* @return     WSEC_SUCCESS on success, other error code on failure.
* @note
*  - Memory operation: allocate memory ctx.
*  - Thread safe:      Thread-safe function.
*  - OS difference:    no OS difference.
*  - Time consuming:   Yes, related to thread, cryptographic computation operation and TEE operations (only TEE mode).
*/
unsigned long SdpEncryptInit(WsecUint32 domain,
    WsecUint32 cipherAlgId,
    WsecUint32 hmacAlgId,
    WsecHandle *ctx,
    SdpBodCipherHeader *bodCipherHeader);

/* Stream Data Encryption-Add */
/**
* @brief      Stream Data Encryption-Add.
* @param[in]  ctx Data protection context, create in SdpEncryptInit.
* @param[in]  plainText Segmented plaintext memory block to be encrypted.
* @param[in]  plainLen Segmented plaintext memory block length to be encrypted.
* @param[out] cipherText Memory block for which the encrypted ciphertext is to be generated.
* @param[out] cipherLen Memory block length for which the encrypted ciphertext is to be generated.
* @return     WSEC_SUCCESS on success, other error code on failure.
* @note
*  - Memory operation: no allocate memory.
*  - Thread safe:      Thread-safe function.
*  - OS difference:    no OS difference.
*  - Time consuming:   Yes, related to thread, cryptographic computation operation.
*/
unsigned long SdpEncryptUpdate(WsecHandle *ctx,
    const unsigned char *plainText,
    WsecUint32 plainLen,
    unsigned char *cipherText,
    WsecUint32 *cipherLen);

/* Stream Data Encryption - Termination */
/**
* @brief      Stream Data Encryption - Termination.
* @param[in]  ctx Data protection context, create in SdpEncryptInit.
* @param[out] cipherText Memory block for generating ciphertext after encryption.
* @param[out] cipherLen Memory block len for generating ciphertext after encryption.
* @param[out] hmacText The memory block of the HMAC after encryption is generated.
* @param[out] hmacLen MThe memory block length of the HMAC after encryption is generated.
* @return     WSEC_SUCCESS on success, other error code on failure.
* @note
*  - Memory operation: no allocate memory.
*  - Thread safe:      Thread-safe function.
*  - OS difference:    no OS difference.
*  - Time consuming:   Yes, related to thread, cryptographic computation operation.
*/
unsigned long SdpEncryptFinal(WsecHandle *ctx,
    unsigned char *cipherText,
    WsecUint32 *cipherLen,
    unsigned char *hmacText,
    WsecUint32 *hmacLen);


/**
 * @brief      Stream data decryption-start.
 * @param[in]  domain The domainID of decrypt key.
 * @param[in]  ctx streaming decryption context information.
 * @param[in]  bodCipherHeader stream decryption ciphertext header.
 * @return     WSEC_SUCCESS on success, other error code on failure.
 * @note
 *  - Memory operation: Allocate memory , In the normal process, the SdpDecryptInit, SdpDecryptUpdate,
                        and SdpDecryptFinal interfaces are invoked to release the ctx.
 *  - Thread safe:      Thread-safe function.
 *  - OS difference:    No.
 *  - Time consumed:    Yes,  related to underlying cryptographic library operations.
 */
unsigned long SdpDecryptInit(WsecUint32 domain,
    WsecHandle *ctx,
    const SdpBodCipherHeader *bodCipherHeader);

/**
 * @brief      Stream Data Decryption-Add.
 * @param[in]  ctx streaming decryption context information.
 * @param[in]  cipherText stream decryption cipher buffer.
 * @param[in]  cipherLen stream decryption cipher buffer len.
 * @param[out]  plainText stream decryption plainText buffer.
 * @param[out]  plainLen stream decryption plainText buffer len.
 * @return     WSEC_SUCCESS on success, other error code on failure.
 * @note
 *  - Memory operation: Allocate and release memory by itself, doesn't need invoker release.
 *  - Thread safe:      Thread-safe function.
 *  - OS difference:    No.
 *  - Time consumed:    Yes,  related to underlying cryptographic library operations.
 */
unsigned long SdpDecryptUpdate(WsecHandle *ctx,
    const unsigned char *cipherText,
    WsecUint32 cipherLen,
    unsigned char *plainText,
    WsecUint32 *plainLen);

/**
 * @brief      Stream data decryption-termination
 * @param[in]  ctx streaming decryption context information.
 * @param[in]  hmacText stream decryption hmac buffer.
 * @param[in]  hmacLen stream decryption hmac buffer len.
 * @param[out] plainText stream decryption plainText buffer.
 * @param[out] plainLen stream decryption plainText buffer len.
 * @return     WSEC_SUCCESS on success, other error code on failure.
 * @note
 *  - Memory operation: Allocate and release memory by itself, doesn't need invoker release.
                        Release the ctx memory applied by SdpDecryptInit in the normal process.
 *  - Thread safe:      Thread-safe function.
 *  - OS difference:    No.
 *  - Time consumed:    Yes, related to underlying cryptographic library operations.
 */
unsigned long SdpDecryptFinal(WsecHandle *ctx,
    const unsigned char *hmacText,
    WsecUint32 hmacLen,
    unsigned char *plainText,
    WsecUint32 *plainLen);

/* Encrypting a File */
unsigned long SdpFileEncrypt(WsecUint32 domain,
    WsecUint32 cipherAlgId,
    WsecUint32 hmacAlgId,
    const char *plainFile,
    const char *cipherFile,
    const CallbackGetFileDateTime getFileDateTime);

/* Decrypting a File */
unsigned long SdpFileDecrypt(WsecUint32 domain,
    const char *cipherFile,
    const char *plainFile,
    const CallbackSetFileDateTime setFileDateTime);

/* Obtain the ciphertext header based on the ciphertext. */
unsigned long SdpGetCipherHeaderV1(const unsigned char *ciphertext, WsecUint32 ciphertextLen,
    SdpCipherHeader *cipherHeader);


/**
 * @brief      Obtains MKInfo based on BodCipherHeader.
 * @param[in]  SdpBodCipherHeader Stream ciphertext header to be searched for.
 * @param[out] KmcMkInfo  Key found in the stream ciphertext header information.
 * @note
 *  - Memory operation: Allocate and release memory by itself, doesn't need invoker release.
 *  - Thread safe:      Thread-safe function.
 *  - OS difference:    No.
 *  - Time consuming:   No.
 */
unsigned long SdpGetMkDetailByBodCipherHeader(SdpBodCipherHeader *bodCipherHeader, KmcMkInfo *mkInfo);

/* Obtain the ciphertext header based on the ciphertext file. */
unsigned long SdpGetMkDetailByCipherFile(const char *cipherFile, KmcMkInfo *mkInfo);

/* Obtain the value of BodCipherHeader based on the ciphertext file. */
unsigned long SdpGetBodCipherHeaderByCipherFile(const char *cipherFile, SdpBodCipherHeader *header);

/* III. Password Protection */
/* Obtains the length of the password protection result. */
size_t SdpGetPwdCipherLen(size_t passwordHashLen);

/* Protection password */
unsigned long SdpProtectPwd(WsecUint32 algId,
    WsecUint32 iter,
    const unsigned char *plainText,
    WsecUint32 plainLen,
    unsigned char *cipherText,
    WsecUint32 cipherLen);

/* Plaintext password authentication */
unsigned long SdpVerifyPwd(const unsigned char *plainText,
    WsecUint32 plainLen,
    const unsigned char *cipherText,
    WsecUint32 cipherLen);

/* HMAC Compatible Interface Prototype in KMCV100 */
/* Obtains the maximum possible HMAC length. */
unsigned long SdpGetHmacLen(WsecUint32 *hmacLen);

unsigned long SdpGetHmacLenMul(WsecHandle kmcCtx, WsecUint32 *hmacLen);

/* Calculates the HMAC of the specified data using the key in the specified domain and the specified algorithm ID. */
unsigned long SdpHmac(WsecUint32 domain,
    WsecUint32 algId,
    const unsigned char *plainText, WsecUint32 plaintextLen,
    unsigned char *hmacData, WsecUint32 *hmacLen);

unsigned long SdpHmacMul(WsecHandle kmcCtx, WsecUint32 domain, WsecUint32 algId, const unsigned char *plainText,
    WsecUint32 plaintextLen, unsigned char *hmacData, WsecUint32 *hmacLen);

/* Check whether the HMAC result is correct. */
unsigned long SdpVerifyHmac(WsecUint32 domain,
    const unsigned char *plainText, WsecUint32 plaintextLen,
    const unsigned char *hmacData, WsecUint32 hmacLen);


/**
 * @brief      Specify the domain and algorithm ID, and obtain SdpHmacAlgAttributes for SdpHmacInit or SdpFileHmac.
 * @param[in]  domain Domain ID of the key used for calculating the HMAC.
 * @param[in]  algId AlgId used for calculating the HMAC.
 * @param[out] hmacAlgAttributes Data structure required for calculating the hmac.
 * @note
 *  - Memory operation: Allocate and release memory by itself, doesn't need invoker release.
 *  - Thread safe:      Thread-safe function.
 *  - OS difference:    No.
 *  - Time consuming:   No.
 */
unsigned long SdpGetHmacAlgAttr(WsecUint32 domain, WsecUint32 algId, SdpHmacAlgAttributes *hmacAlgAttributes);

/* Specify a domain, specify SdpHmacAlgAttributes, and obtain ctx for SdpHmacUpdate and SdpHmacFinal. */
unsigned long SdpHmacInit(WsecUint32 domain, const SdpHmacAlgAttributes *hmacAlgAttributes, WsecHandle *ctx);

/* Performs HMAC on data and can be invoked for multiple times. */
unsigned long SdpHmacUpdate(WsecHandle *ctx, const unsigned char *plainText, WsecUint32 plaintextLen);

/* Obtains the HMAC of specified data in SdpHmacUpdate. */
unsigned long SdpHmacFinal(WsecHandle *ctx, unsigned char *hmacData, WsecUint32 *hmacLen);

/* Specify the domain, SdpHmacAlgAttributes, and file path to obtain the HMAC result of the file data. */
unsigned long SdpFileHmac(WsecUint32 domain,
    const char *file,
    const SdpHmacAlgAttributes *hmacAlgAttributes,
    WsecVoid *hmacData, WsecUint32 *hmacLen);

/* Specify the domain, SdpHmacAlgAttributes, file path, file data HMAC, and HMAC authentication. */
unsigned long SdpVerifyFileHmac(WsecUint32 domain,
    const char *file,
    const SdpHmacAlgAttributes *hmacAlgAttributes,
    const WsecVoid *hmacData, WsecUint32 hmacLen);

/* Obtains MKInfo based on hmacData. */
unsigned long SdpGetMkDetailByHmacData(WsecVoid *hmacData, WsecUint32 hmacLen, KmcMkInfo *mkInfo);

/**
 * @brief      Get mac len by symAlgId and hmacAlgId.
 * @param[in]  cipherAlgId Encryption algorithm.
 * @param[in]  hmacAlgId Hmac algId.
 * @param[out] macLen Mac Length calculated based on the algorithm.
 * @note
 *  - Memory operation: Allocate and release memory by itself, doesn't need invoker release.
 *  - Thread safe:      Thread-safe function.
 *  - OS difference:    No.
 *  - Time consuming:   No.
 */
unsigned long SdpGetMacLenForEncrypt(WsecUint32 cipherAlgId, WsecUint32 hmacAlgId, WsecUint32 *macLen);

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

#endif /* KMC_SRC_SDP_SDPV1_ITF_H */
